﻿/** 
 * The Scene
 */
 
 import SCUMMCore.*;
 import DepthAndScaleEngine.*;
 import SCUMMCore.States.*;
 import SCUMMCore.Nodes.*;
 import SCUMMCharacter.*;
 import SCUMMGameControl.*;

 
class SCUMMScenario.SCUMMScene extends SCUMMObject {
	/** Fields **/
	private var nOriginalScenarioY:Number;
	private var oGame:SCUMMGame;
	private var bCanWalk:Boolean;
	private var oGraph:NodeCollection;
	private var mcWalkableArea:MovieClip;
	private var btnClickableArea:Button;
	private var aListEvent:Array;
	private var oCurrentEvent:Event;
	private var oMainActor:SCUMMActor;
	private var oActorCamera:SCUMMActor;
	private var oActionsBar:SCUMMActionBar;
	public var oDepthHandler:DepthHandler;
	private	var frameIndex:Number;
	public var arObjectsArray:Array;
	/** Property **/
	public function get listEvent():Array {
		return this.aListEvent;
	}
	
	public function get walkableArea():MovieClip {
		return this.mcWalkableArea;
	}
	public function set walkableArea( value:MovieClip ):Void {
		this.mcWalkableArea = walkableArea;
	}

	public function get clickableArea():Button {
		return this.btnClickableArea;
	}
	public function set clickableArea( value:Button ):Void {
		this.btnClickableArea = value;
	}
	
	public function get currentEvent():Event {
		return this.oCurrentEvent;
	}
	
	public function get game():SCUMMGame {
		return this.oGame;
	}
	
	public function get canWalk():Boolean {
		return this.bCanWalk;
	}
	public function set canWalk( value:Boolean ):Void {
		this.bCanWalk = value;
	}
	
	public function setMainActor( value:SCUMMActor ):Void {
		this.oMainActor = value;
	}
	public function get mainActor():SCUMMActor  {
		return this.oMainActor;
	}

	public function setActorCamera( value:SCUMMActor ):Void {
		this.oActorCamera = value;
	}
	public function get actorCamera():SCUMMActor  {
		return this.oActorCamera;
	}
		
	/** Methods **/
	public function SCUMMScene( poGame:SCUMMGame, pmcScenario:MovieClip) {
		this.arObjectsArray = new Array();
		this.oDepthHandler = new DepthHandler();
		if ( pmcScenario.WalkableArea == undefined) {
			throw new Error("SCUMMScene - Error: Walkable area can't be null");
		}
		if ( pmcScenario.ClickableArea == undefined )
			throw new Error("SCUMMScene - Error: Clickable area can't be null");
		
		if ( poGame == null )
			throw new Error("SCUMMScene - Error: Clickable area can't be null");
		this.nOriginalScenarioY = pmcScenario._y;
		this.bCanWalk = true;
		this.oGame = poGame;
		this.frameIndex = pmcScenario._parent._currentFrame;
		this.mcSprite = pmcScenario;
		this.mcWalkableArea = pmcScenario.WalkableArea;
		this.btnClickableArea = pmcScenario.ClickableArea;
		this.oGraph = new NodeCollection();
		this.aListEvent = new Array();
		this.addNodeColection();		
		var oScene:SCUMMScene = this;
 		//This is the main loop implementation. In every frame, the "centerView" method is called.
 		this.mcSprite.onEnterFrame = function() {
 			oScene.oDepthHandler.rearrangeDepths();
 			oScene.centerView();
 		};
 		//Code for handle the click actions in the game(by catrina)
 		this.btnClickableArea.useHandCursor = false;
 		this.btnClickableArea.onRelease = function() {
 			if ( oScene.listEvent.length > 0 ) {
 				oScene.currentEvent.finishEvent();
 			}
 			//Checks if the status of the game is Talking
			else if ( oScene.canWalk && _global.SCUMMGame.isExploring()) {
				oScene.oMainActor.walkTo(
					oScene.mc._xmouse,
					oScene.mc._ymouse
				);
			}
		};
		
		
	}
	public function addObjectToArrange(pObject:MovieClip){
		this.oDepthHandler.addObjectToArrange(pObject);
	}
	public function crateMainActor( pmcSprite:MovieClip, pmcTextContainer:MovieClip ):SCUMMActor {
  		if( pmcSprite == undefined )
			throw new Error("SCUMMScene - Error: The sprite of the main actor can't be null");
 		this.oMainActor = new SCUMMActor(pmcSprite, this, pmcTextContainer);
		this.oMainActor.mc.onRollOver = null;		
 		this.oActorCamera = this.oMainActor;
		if(oGame.nMainActorX!=undefined && oGame.nMainActorY!=undefined){
			this.oMainActor.mc._x = oGame.nMainActorX;
			this.oMainActor.mc._y = oGame.nMainActorY;
		}
 		return this.oMainActor;
 	}
	
	function createObject(p_mc:MovieClip):SCUMMObject{
		var oReturnObject:SCUMMObject;
		oReturnObject = new SCUMMObject(p_mc);
		if(this.oGame.states[this.frameIndex+"_"+p_mc._name]){
			p_mc._currentFrame = this.oGame.states[this.frameIndex+"_"+p_mc._name].currentFrame;
			p_mc._x = this.oGame.states[this.frameIndex+"_"+p_mc._name]._x;
			p_mc._y = this.oGame.states[this.frameIndex+"_"+p_mc._name]._y;
			p_mc._visible = this.oGame.states[this.frameIndex+"_"+p_mc._name]._visible;
		}
		this.arObjectsArray.push(oReturnObject);
		return oReturnObject;
	}
	
	function saveAllStates(){
		var i:Number;
		var strLabel:String;
		_global.SCUMMGame.states[this.frameIndex] = new Array();
		for(i=0;i<this.arObjectsArray.length;i++){
			_global.SCUMMGame.states[this.frameIndex][i] =  new Object();
			_global.SCUMMGame.states[this.frameIndex][i].currentFrame=this.arObjectsArray[i].mc._currentframe;
			_global.SCUMMGame.states[this.frameIndex][i].name=this.arObjectsArray[i].mc._name;
			_global.SCUMMGame.states[this.frameIndex][i]._x = this.arObjectsArray[i].mc._x;
			_global.SCUMMGame.states[this.frameIndex][i]._y = this.arObjectsArray[i].mc._y;
			_global.SCUMMGame.states[this.frameIndex][i]._visible = this.arObjectsArray[i].mc._visible;
		}
	}
	
	function loadAllStates(){
		var i:Number;
		for(i=0;i<this.arObjectsArray.length;i++){
			this.arObjectsArray[i].mc.gotoAndStop(_global.SCUMMGame.states[this.frameIndex][i].currentFrame);
			this.arObjectsArray[i].mc._x = _global.SCUMMGame.states[this.frameIndex][i]._x;
			this.arObjectsArray[i].mc._y = _global.SCUMMGame.states[this.frameIndex][i]._y;
			this.arObjectsArray[i].mc._visible = _global.SCUMMGame.states[this.frameIndex][i]._visible;
		}
	}
	
	private function nodeCompareFunctionForSort(a:Object, b:Object){
		var cmpA:Number;
		var cmpB:Number;
		cmpA = new Number(a.split("__")[0].split("_")[1]);
		cmpB = new Number(b.split("__")[0].split("_")[1]);
		return cmpA-cmpB;
	}
	// Temporário
	private function addNodeColection()
	{
		var aNodes:Array = new Array();
		
		for ( var x:String in this.mcSprite ){
			if ( x.substr(0, 7) == "myNodo_" ){
				aNodes.push(x);
			}
		}
		aNodes.sort(this.nodeCompareFunctionForSort);
		
		var oNode:Node;
		var arrChilds:Array;
		for ( var i = 0; i < aNodes.length; i++ ) {
			oNode = new Node(this.mcSprite[aNodes[i]]);
			this.mcSprite[aNodes[i]]._name = aNodes[i].split("__")[0];
			arrChilds = aNodes[i].split("__")[1].split("_");
			if(arrChilds!=undefined){
				for(var t = 0; t<arrChilds.length; t++){
					//trace(new Number(arrChilds[t]));
					oNode.addChild(new Number(arrChilds[t]));	
				}
			}
			this.oGraph.addNode(oNode);
		}
		
	}
	
	/*
	private function addNodeColection()
	{
	{
		var aNodes:Array = new Array();
		
		for ( var x:String in this.mcSprite )
			if ( x.substr(0, 7) == "myNodo_" )
				aNodes.push(x);
		aNodes.sort();
		
		var oNode:Node;
		
		for ( var i = 0; i < aNodes.length; i++ ) {
			oNode = new Node(this.mcSprite[aNodes[i]]);
			if ( i != 0 )
				oNode.addChild(i - 1);
			if ( i != (aNodes.length - 1) )
				oNode.addChild(i + 1);
			this.oGraph.addNode(oNode);
		}
		
	}
	*/
	
	public function findPath(init_x:Number, init_y:Number, end_x:Number, end_y:Number):NodeCollection {
		var myNode:Node = new Node();
		myNode._x = init_x;
		myNode._y = init_y;
		var NodoInicio:Node = this.oGraph.getCloserNode(myNode);
		myNode._x = end_x;
		myNode._y = end_y;
		var NodoFin:Node = this.oGraph.getCloserNode(myNode);
		return this.oGraph.findPath(NodoInicio, NodoFin);
	}
	//Add a walk to the actions queue. usefull for creating animations.
	public function addWalk( poActor:SCUMMActor, x:Number, y:Number ):Void {
		var oEvento:Event = Event.actorWalkTo(poActor, x, y);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 )
			oEvento.run();
	}
	//Add a speak to the actions queue. usefull for creating animations.	
	public function addSpeak( actor:SCUMMActor, text:Array ):Void {
		var oEvento:Event = Event.actorSpeak(text, actor);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 ) {
			this.oCurrentEvent = oEvento;
			oEvento.run();
		}
	}
	//Add a walk to the actions queue. usefull for creating animations.
	public function addGetObject(poObject:SCUMMObject):Void {
		var oEvento:Event = Event.actorGetObject(poObject, this);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 )
			oEvento.run();
	}
	/*
	add a disableActionsVar event to the actions queue
	
	@author: Pablo Weremczuk
	@return: Event
	*/
	public function addDisableActionsBar():Void {
		var oEvento:Event = Event.disableActionsBar(this);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 )
			oEvento.run();
	}
	/*
	add a enableActionsVar event to the actions queue
	
	@author: Pablo Weremczuk
	@return: Event
	*/
	public function addEnableActionsBar():Void {
		var oEvento:Event = Event.enableActionsBar(this);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 )
			oEvento.run();
	}
	
	public function addAnimation( sprite:MovieClip ):Void {
		var oEvento:Event = Event.animation(sprite, this);
		this.aListEvent.push(oEvento);
		if ( this.aListEvent.length == 1 ) {
			this.oCurrentEvent = oEvento;
			this.oCurrentEvent.run();
		}
	}
	
	public function endEvent():Void {
		this.aListEvent.shift();
		if ( this.aListEvent.length > 0 ) {
			this.oCurrentEvent = Event(this.aListEvent[0]);
			this.oCurrentEvent.run();
		}
	}
	//This function follow the actor for the scene.
	public function centerView():Void {
		var actorPoint:Object = {
			x:this.oActorCamera.mc._x,
			y:this.oActorCamera.mc._y
		};
		this.mcSprite.localToGlobal(actorPoint);
		
		
		// center view X
		if ( actorPoint.x >= Stage.width/2 ) {
			if ( (this.mcSprite._width - Math.abs(this.mcSprite._x) - Stage.width) >= (actorPoint.x - Stage.width/2) ) {
				this.mcSprite._x -= actorPoint.x - Stage.width/2;
			}else {//if the scenario is at the rightmost position, you stop moving it, or you willl show the border of it.
				this.mcSprite._x =  Stage.width - this.mcSprite._width;
			}
		}else{
			if ( this.mcSprite._x < (actorPoint.x - Stage.width/2) ) {
				this.mcSprite._x -= actorPoint.x - Stage.width/2;
			}
			else {
				this.mcSprite._x = 0;
			}
		}

		// center view Y
		var viewPortHeight:Number = (Stage.height-_global.ActionBar.mc._height);
		if ( actorPoint.y >= viewPortHeight/2 ) {
			if ( (this.mcSprite._height - Math.abs(this.mcSprite._y) - viewPortHeight) >= (actorPoint.y - viewPortHeight/2) ) {
				this.mcSprite._y -= actorPoint.y - viewPortHeight/2;
			}else {
				this.mcSprite._y =  viewPortHeight - this.mcSprite._height;
			}
		} else {
			if ( this.mcSprite._y < (actorPoint.y - viewPortHeight/2) ) {
				this.mcSprite._y -= actorPoint.y - viewPortHeight/2;
			}
			else {
				this.mcSprite._y = this.nOriginalScenarioY;
			}
		}
		
	}
}